/*
 * cobit.h
 *
 *  Created on: 2015��8��26��
 *      Author: huangkaibin
 */

#ifndef _COBIT_H_
#define _COBIT_H_

#include "typedef.h"

extern const uint8 _PowOfTwo_8[8];
extern const uint16 _PowOfTwo_16[16];
extern const uint32  _PowOfTwo_32[32];


#define drsys_lock_cpu() \
do { \
	__DI(); \
} while(0)

#define drsys_unlock_cpu() \
do { \
	__EI(); \
} while(0)


#define byteop_power_2_array (_PowOfTwo_8)
#define wordop_power_2_array (_PowOfTwo_16)
#define dwordop_power_2_array (_PowOfTwo_32)

//#define byteop_power_2(exp) ((uint8)(byteop_power_2_array[exp]))
//#define wordop_power_2(exp) ((uint16)(wordop_power_2_array[exp]))
//#define dwordop_power_2(exp) ((uint32)(dwordop_power_2_array[exp]))

#define byteop_power_2(exp)  ((uint8)((uint8)1U<<(exp)))
#define wordop_power_2(exp)  ((uint16)((uint16)1U<<(exp)))
#define dwordop_power_2(exp) ((uint32)((uint32)1UL<<(exp)))


extern uint8 byteop_count_bit_one(uint8 data);
extern uint8 byteop_count_bit_zero(uint8 data);
extern uint8 wordop_count_bit_one(uint16 data);
extern uint8 wordop_count_bit_zero(uint16 data);
extern uint8 dwordop_count_bit_one(uint32 data);
extern uint8 dwordop_count_bit_zero(uint32 data);

#define byteop_generate_bits(startbit, bitcount)  ((uint8)((uint8)(byteop_power_2(bitcount) - 1U) << (startbit)))
#define wordop_generate_bits(startbit, bitcount)  ((uint16)((uint16)(wordop_power_2(bitcount) - 1U) << (startbit)))
#define dwordop_generate_bits(startbit, bitcount) ((uint32)((uint32)(dwordop_power_2(bitcount) - 1U) << (startbit)))

#define byteop_generate_mask_bits(startbit, bitcount)   ((uint8) (~(byteop_generate_bits(startbit, bitcount))))
#define wordop_generate_mask_bits(startbit, bitcount)   ((uint16)(~(wordop_generate_bits(startbit, bitcount))))
#define dwordop_generate_mask_bits(startbit, bitcount)  ((uint32)(~(dwordop_generate_bits(startbit, bitcount))))


#define byteop_bitset(data, bitmask)   ((data) |= (uint8)(bitmask))
#define wordop_bitset(data, bitmask)   ((data) |= (uint16)(bitmask))
#define dwordop_bitset(data, bitmask)  ((data) |= (uint32)(bitmask))
#define byteop_bitset_at(data, bitidx) ((data) |= byteop_power_2(bitidx))
#define wordop_bitset_at(data, bitidx) ((data) |= wordop_power_2(bitidx))
#define dwordop_bitset_at(data, bitidx) ((data) |= dwordop_power_2(bitidx))

#define byteop_bitreverse(data, bitmask)    ((data) ^= (uint8)(bitmask))
#define wordop_bitreverse(data, bitmask)    ((data) ^= (uint16)(bitmask))
#define dwordop_bitreverse(data, bitmask)   ((data) ^= (uint32)(bitmask))
#define byteop_bitreverse_at(data, bitidx)  ((data) ^=  byteop_power_2(bitidx))
#define wordop_bitreverse_at(data, bitidx)  ((data) ^=  wordop_power_2(bitidx))
#define dwordop_bitreverse_at(data, bitidx) ((data) ^=  dwordop_power_2(bitidx))

#define byteop_bitclear(data, bitmask)    ((data) &= (uint8) (~((uint8) (bitmask))))
#define wordop_bitclear(data, bitmask)    ((data) &= (uint16)(~((uint16)(bitmask))))
#define dwordop_bitclear(data, bitmask)   ((data) &= (uint32)(~((uint32)(bitmask))))
#define byteop_bitclear_at(data, bitidx)  ((data) &= (uint8) (~(byteop_power_2(bitidx))))
#define wordop_bitclear_at(data, bitidx)  ((data) &= (uint16)(~(wordop_power_2(bitidx))))
#define dwordop_bitclear_at(data, bitidx) ((data) &= (uint32)(~(dwordop_power_2(bitidx))))



#define byteop_bittest(data, bitmask)    (((uint8) (data) & (uint8) (bitmask)) != 0U)
#define wordop_bittest(data, bitmask)    (((uint16)(data) & (uint16)(bitmask)) != 0U)
#define dwordop_bittest(data, bitmask)   (((uint32)(data) & (uint32)(bitmask)) != 0U)
#define byteop_bittest_at(data, bitidx)  (((uint8) (data) & byteop_power_2(bitidx)) != 0U)
#define wordop_bittest_at(data, bitidx)  (((uint16)(data) & wordop_power_2(bitidx)) != 0U)
#define dwordop_bittest_at(data, bitidx) (((uint32)(data) & dwordop_power_2(bitidx)) != 0U)



#define byteop_bitwrite(data, bitmask, bitvalue)     ((data) =  ((uint8)(((uint8)(data) & (uint8)(~((uint8)(bitmask)))) | (uint8)(bitvalue))))
#define wordop_bitwrite(data, bitmask, bitvalue)     ((data) =  ((uint16)(((uint16)(data) & (uint16)(~((uint16)(bitmask)))) | (uint16)(bitvalue))))
#define dwordop_bitwrite(data, bitmask, bitvalue)    ((data) = ((uint32)(((uint32)(data) & (uint32)(~((uint32)(bitmask)))) | (uint32)(bitvalue))))
#define byteop_bitwrite_at(data, bitidx, bitvalue)   byteop_bitwrite(data,  ((uint8) 1U << (bitidx)), (((bitvalue) & 0x01U) << (bitidx)))
#define wordop_bitwrite_at(data, bitidx, bitvalue)   wordop_bitwrite(data,  ((uint16)1U << (bitidx)), (((bitvalue) & 0x01U) << (bitidx)))
#define dwordop_bitwrite_at(data, bitidx, bitvalue)  dwordop_bitwrite(data, ((uint32)1U << (bitidx)), (((bitvalue) & 0x01U) << (bitidx)))
#define byteop_bitwrite_at_bits(data, startbit, bitcount, value)   byteop_bitwrite(data,   byteop_generate_bits(startbit, bitcount), ((uint8)(value) << (startbit)))
#define wordop_bitwrite_at_bits(data, startbit, bitcount, value)   wordop_bitwrite(data,   byteop_generate_bits(startbit, bitcount), ((uint16)(value) << (startbit)))
#define dwordop_bitwrite_at_bits(data, startbit, bitcount, value)  dwordop_bitwrite(data,  byteop_generate_bits(startbit, bitcount), ((uint32)(value) << (startbit)))


#define byteop_read_byte_from_near_address(address)   ((uint8)(*((const uint8*)(address))))
#define wordop_read_word_from_near_address(address)   ((uint16)(*((const uint16*)(address))))
#define dwordop_read_dword_from_near_address(address) ((uint32)(*((const uint32*)(address))))

#define byteop_read_byte_from_far_address(address)                ((uint8)(*((const fpuint8)(address))))
#define wordop_read_word_from_far_address(address)                ((uint16)(*((const fpuint16)(address))))
#define dwordop_read_dword_from_far_address(address)              ((uint32)(*((const fpuint32)(address))))

#define byteop_read_byte_from_global_address(address)   ((uint8)(*((const fpuint8)((drflash_convert_global_to_logic_address(address))))))
#define wordop_read_word_from_global_address(address)   ((uint16)(*((const fpuint16)((drflash_convert_global_to_logic_address(address))))))
#define dwordop_read_dword_from_global_address(address) ((uint32)(*((const fpuint32)((drflash_convert_global_to_logic_address(address))))))


#define wordop_fill_data_buffer_little_endian(buffer, offset, value) \
do { \
	(buffer)[(offset)] =     (uint8)(value); /*lower byte*/ \
	(buffer)[(offset) + 1U] = (uint8)(((value) >> 8U) & 0xFFU); /*higher byte*/ \
} while(0)

#define dwordop_fill_data_buffer_little_endian(buffer, offset, value) \
do { \
	(buffer)[(offset)] =     (uint8)(value);                    /*lower byte*/ \
	(buffer)[(offset) + 1U] = (uint8)(((value) >>  8U) & 0xFFU);  \
	(buffer)[(offset) + 2U] = (uint8)(((value) >> 16U) & 0xFFU); \
	(buffer)[(offset) + 3U] = (uint8)(((value) >> 24U) & 0xFFU); /*higher byte*/ \
} while(0)


#define wordop_fill_data_buffer_big_endian(buffer, offset, value) \
do { \
	(buffer)[(offset)] =      (uint8)(((value) >> 8U) & 0xFFU); /*higher byte*/ \
	(buffer)[(offset) + 1U] = (uint8)(value); /*lower byte*/ \
} while(0)

#define dwordop_fill_data_buffer_big_endian(buffer, offset, value) \
do { \
	(buffer)[(offset)] =      (uint8)(((value) >> 24U) & 0xFFU); /*higher byte*/ \
	(buffer)[(offset) + 1U] = (uint8)(((value) >> 16U) & 0xFFU); \
	(buffer)[(offset) + 2U] = (uint8)(((value) >>  8U) & 0xFFU); \
	(buffer)[(offset) + 3U] = (uint8)(value);                    /*lower byte*/ \
} while(0)

//TODO, ml, class9, what fking following code violates natural pointer alignment, find the involving guy
/*
#define wordop_fill_data_buffer_big_endian(buffer, offset, value) \
do { \
	(*((uint16 *)((uint8*)(buffer) + (offset)))) = (uint16)(value); \
} while(0)

#define dwordop_fill_data_buffer_big_endian(buffer, offset, value) \
do { \
	(*((uint32 *)((uint8*)(buffer) + (offset)))) = (uint32)(value); \
} while(0)
*/


#define wordop_make_data_little_endian(buffer, offset) ((uint16)(((uint16)((buffer)[(offset) + 1U]) << 8U) | ((uint16)((buffer)[(offset) + 0U]))))
#define dwordop_make_data_little_endian(buffer, offset) ((uint32)(((uint32)((buffer)[(offset) + 3U]) << 24U) | ((uint32)((buffer)[(offset) + 2U]) << 16U) | ((uint32)((buffer)[(offset) + 1U]) << 8U) | ((uint32)((buffer)[(offset) + 0U]))))



#define wordop_make_data_big_endian(buffer, offset) ((uint16)(((uint16)((buffer)[(offset)]) << 8U) | ((uint16)((buffer)[(offset) + 1U]))))
#define dwordop_make_data_big_endian(buffer, offset) ((uint32)(((uint32)((buffer)[(offset) + 0U]) << 24U) | ((uint32)((buffer)[(offset) + 1U]) << 16U) | ((uint32)((buffer)[(offset) + 2U]) << 8U) | ((uint32)((buffer)[(offset) + 3U]))))

//TODO, ml, class9, what fking following code violates natural pointer alignment, find the involving guy
//#define wordop_make_data_big_endian(buffer, offset) ((uint16)(*((const uint16*)(((const uint8*)(buffer)) + (offset)))))
//#define dwordop_make_data_big_endian(buffer, offset) ((uint32)(*((const uint32*)(((const uint8*)(buffer)) + (offset)))))


#define byteop_bitset_withlock(data, bitmask) \
do { \
	drsys_lock_cpu(); \
	byteop_bitset(data, bitmask); \
	drsys_unlock_cpu(); \
} while(0)

#define wordop_bitset_withlock(data, bitmask) \
do { \
	drsys_lock_cpu(); \
	wordop_bitset(data, bitmask); \
	drsys_unlock_cpu(); \
} while(0)

#define byteop_bitset_at_withlock(data, bitidx) \
do { \
	drsys_lock_cpu(); \
	byteop_bitset_at(data, bitidx); \
	drsys_unlock_cpu(); \
} while(0)

#define wordop_bitset_at_withlock(data, bitidx) \
do { \
	drsys_lock_cpu(); \
	wordop_bitset_at(data, bitidx); \
	drsys_unlock_cpu(); \
} while(0)


#define byteop_bitclear_at_withlock(data, bitidx) \
do { \
	drsys_lock_cpu(); \
	byteop_bitclear_at(data, bitidx); \
	drsys_unlock_cpu(); \
} while(0)

#define wordop_bitclear_at_withlock(data, bitidx) \
do { \
	drsys_lock_cpu(); \
	wordop_bitclear_at(data, bitidx); \
	drsys_unlock_cpu(); \
} while(0)


#define byteop_bitclear_withlock(data, bitmask) \
do { \
	drsys_lock_cpu(); \
	byteop_bitclear(data, bitmask); \
	drsys_unlock_cpu(); \
} while(0)

#define wordop_bitclear_withlock(data, bitmask) \
do { \
	drsys_lock_cpu(); \
	wordop_bitclear(data, bitmask); \
	drsys_unlock_cpu(); \
} while(0)

#define byteop_bitwrite_withlock(data, bitmask, bitvalue) \
do { \
	drsys_lock_cpu(); \
	byteop_bitwrite(data, bitmask, bitvalue); \
	drsys_unlock_cpu(); \
} while(0)

#define wordop_bitwrite_withlock(data, bitmask, bitvalue) \
do { \
	drsys_lock_cpu(); \
	wordop_bitwrite(data, bitmask, bitvalue); \
	drsys_unlock_cpu(); \
} while(0)

#define byteop_bitwrite_at_withlock(data, bitmask, bitvalue) \
do { \
	drsys_lock_cpu(); \
	byteop_bitwrite_at(data, bitmask, bitvalue); \
	drsys_unlock_cpu(); \
} while(0)

#define wordop_bitwrite_at_withlock(data, bitmask, bitvalue) \
do { \
	drsys_lock_cpu(); \
	wordop_bitwrite_at(data, bitmask, bitvalue); \
	drsys_unlock_cpu(); \
} while(0)

#endif /* _COBIT_H_ */
